home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / ax25cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-25  |  21.6 KB  |  1,026 lines

  1. /* AX25 control commands
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  * 
  4.  * Mods by G1EMM
  5.  * Mods by PA0GRI
  6.  * Mods by N1BEE
  7.  */
  8. /*
  9. ** FILE: ax25cmd.c
  10. **
  11. ** AX.25 command handler.
  12. **
  13. ** 09/24/90 Bob Applegate, wa2zzx
  14. **    Added BCTEXT, BC, and BCINTERVAL commands for broadcasting an id
  15. **    string using UI frames.
  16. **
  17. ** 27/09/91 Mike Bilow, N1BEE
  18. **    Added Filter command for axheard control
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <dos.h>
  23. #include "global.h"
  24. #include "config.h"
  25. #include "mbuf.h"
  26. #include "timer.h"
  27. #include "proc.h"
  28. #include "iface.h"
  29. #include "ax25.h"
  30. #include "lapb.h"
  31. #include "cmdparse.h"
  32. #include "socket.h"
  33. #include "mailbox.h"
  34. #include "session.h"
  35. #include "tty.h"
  36. #include "nr4.h"
  37. #include "commands.h"
  38. #include "pktdrvr.h"
  39.  
  40. int axheard __ARGS((struct iface *ifp));
  41. static void axflush __ARGS((struct iface *ifp));
  42. static int doaxfilter __ARGS((int argc,char *argv[],void *p));
  43. static int doaxflush __ARGS((int argc,char *argv[],void *p));
  44. static int doaxirtt __ARGS((int argc,char *argv[],void *p));
  45. static int doaxkick __ARGS((int argc,char *argv[],void *p));
  46. static int doaxreset __ARGS((int argc,char *argv[],void *p));
  47. static int doaxroute __ARGS((int argc,char *argv[],void *p));
  48. static int doaxstat __ARGS((int argc,char *argv[],void *p));
  49. static int doaxwindow __ARGS((int argc,char *argv[],void *p));
  50. static int dobc __ARGS((int argc,char *argv[],void *p));
  51. static int dobcint __ARGS((int argc,char *argv[],void *p));
  52. static int dobcport __ARGS((int argc,char *argv[],void *p));
  53. static int dobctext __ARGS((int argc,char *argv[],void *p));
  54. static int doaxhport __ARGS((int argc,char *argv[],void *p));
  55. static int doaxhsize __ARGS((int argc,char *argv[],void *p));
  56. static int doblimit __ARGS((int argc,char *argv[],void *p));
  57. static int dodigipeat __ARGS((int argc,char *argv[],void *p));
  58. static int domaxframe __ARGS((int argc,char *argv[],void *p));
  59. static int domycall __ARGS((int argc,char *argv[],void *p));
  60. static int don2 __ARGS((int argc,char *argv[],void *p));
  61. static int dopaclen __ARGS((int argc,char *argv[],void *p));
  62. static int dopthresh __ARGS((int argc,char *argv[],void *p));
  63. static int dot3 __ARGS((int argc,char *argv[],void *p));
  64. static int doaxtype __ARGS((int argc,char *argv[],void *p));
  65. static int dot4 __ARGS((int argc,char *argv[],void *p));
  66. static int doversion __ARGS((int argc,char *argv[],void *p));
  67. static int dotutorcall __ARGS((int argc,char *argv[],void *p));
  68. static int doinfocall __ARGS((int argc,char *argv[],void *p));
  69. static int donewscall __ARGS((int argc,char *argv[],void *p));
  70. static void ax_bc __ARGS((struct iface *axif));
  71. static int axdest __ARGS((struct iface *ifp));
  72.  
  73. extern int axheard_filter_flag;        /* in axheard.c */
  74. /* Defaults for IDing. */
  75. char *axbctext = NULL;                /* Text to send */
  76. static struct timer Broadtimer;    /* timer for broadcasts */
  77. extern char Tcall[AXALEN];
  78. extern char Icall[AXALEN];
  79. extern char Ncall[AXALEN];
  80.  
  81. char *Ax25states[] = {
  82.     "",
  83.     "Disconnected",
  84.     "Listening",
  85.     "Conn pending",
  86.     "Disc pending",
  87.     "Connected",
  88.     "Recovery",
  89. };
  90.  
  91. /* Ascii explanations for the disconnect reasons listed in lapb.h under
  92.  * "reason" in ax25_cb
  93.  */
  94. char *Axreasons[] = {
  95.     "Normal",
  96.     "DM received",
  97.     "Timeout"
  98. };
  99.  
  100. static struct cmds DFAR Axcmds[] = {
  101.     "bc",        dobc,        0, 0, NULLCHAR,
  102.     "bcinterval",    dobcint,    0, 0, NULLCHAR,
  103.     "bcport",    dobcport,    0, 0, NULLCHAR,
  104.     "blimit",    doblimit,    0, 0, NULLCHAR,
  105.     "bctext",    dobctext,    0, 0, NULLCHAR,
  106.     "digipeat",    dodigipeat,    0, 0, NULLCHAR,
  107.     "filter",    doaxfilter,    0, 0, NULLCHAR,
  108.     "flush",    doaxflush,    0, 0, NULLCHAR,
  109.     "heard",    doaxheard,    0, 0, NULLCHAR,
  110.     "hearddest",    doaxdest,    0, 0, NULLCHAR,
  111.     "hport",    doaxhport,    0, 0, NULLCHAR,
  112.     "hsize",    doaxhsize,    0, 0, NULLCHAR,
  113. #ifdef TUTOR
  114.     "infocall",     doinfocall,     0, 0, NULLCHAR,
  115. #endif
  116.     "irtt",        doaxirtt,    0, 0, NULLCHAR,
  117.     "kick",        doaxkick,    0, 2, "ax25 kick <axcb>",
  118.     "maxframe",    domaxframe,    0, 0, NULLCHAR,
  119.     "mycall",    domycall,    0, 0, NULLCHAR,
  120. #ifdef TUTOR
  121.     "newscall",     donewscall,     0, 0, NULLCHAR,
  122. #endif
  123.     "paclen",    dopaclen,    0, 0, NULLCHAR,
  124.     "pthresh",    dopthresh,    0, 0, NULLCHAR,
  125.     "reset",    doaxreset,    0, 2, "ax25 reset <axcb>",
  126.     "retry",    don2,        0, 0, NULLCHAR,
  127.     "route",    doaxroute,    0, 0, NULLCHAR,
  128.     "status",    doaxstat,    0, 0, NULLCHAR,
  129.     "t3",        dot3,        0, 0, NULLCHAR,
  130.     "t4",        dot4,        0, 0, NULLCHAR,
  131.     "timertype",    doaxtype,    0, 0, NULLCHAR,
  132. #ifdef TUTOR
  133.     "tutorcall",    dotutorcall,    0, 0, NULLCHAR,
  134. #endif
  135.     "version",    doversion,    0, 0, NULLCHAR,
  136.     "window",    doaxwindow,    0, 0, NULLCHAR,
  137.     NULLCHAR,
  138. };
  139. /* Multiplexer for top-level ax25 command */
  140. int
  141. doax25(argc,argv,p)
  142. int argc;
  143. char *argv[];
  144. void *p;
  145. {
  146.     return subcmd(Axcmds,argc,argv,p);
  147. }
  148.  
  149.  
  150.  
  151. /*
  152. ** This function is called to send the current broadcast message
  153. ** and reset the timer.
  154. */
  155.  
  156. static int dobc(argc,argv,p)
  157. int argc;
  158. char *argv[];
  159. void *p;
  160. {
  161.     struct iface *ifa;
  162.  
  163.     if (argc < 2)    {
  164.         tprintf("you need to specify an interface\n");
  165.         return 1;
  166.     }
  167.  
  168.     ifa = Ifaces;
  169.     while (ifa != NULL && stricmp(ifa->name,argv[1]))
  170.         ifa = ifa->next;
  171.     if (ifa == NULL)
  172.         tprintf("unknown interface\n");
  173.     else if (ifa->type != CL_AX25)
  174.         tprintf("not an AX.25 interface\n");
  175.     else    {
  176.         ax_bc(ifa);
  177.         stop_timer(&Broadtimer) ;    /* in case it's already running */
  178.         start_timer(&Broadtimer);        /* and fire it up */
  179.     }
  180.     return 0;
  181. }
  182.  
  183.  
  184.  
  185. /*
  186. ** View/Change the message we broadcast.
  187. */
  188.  
  189. static int dobctext(argc,argv,p)
  190. int argc;
  191. char *argv[];
  192. void *p;
  193. {
  194.     if (argc < 2)
  195.         tprintf("Broadcast text: %s\n",axbctext);
  196.     else    {
  197.         if (axbctext != NULL) free(axbctext);
  198.         axbctext = malloc(strlen(argv[1]));
  199.         strcpy(axbctext,argv[1]);
  200.     }
  201.     return 0;
  202. }
  203.  
  204.  
  205. #define TICKSPERSEC    (1000L / MSPTICK)    /* Ticks per second */
  206.  
  207. /*
  208. ** Examine/change the broadcast interval.
  209. */
  210.  
  211. static int dobcint(argc,argv,p)
  212. int argc;
  213. char *argv[];
  214. void *p;
  215. {
  216.     void dobroadtick();
  217.  
  218.     if(argc < 2)    {
  219.         tprintf("Broadcast timer %lu/%lu seconds\n",
  220.             read_timer(&Broadtimer)/1000L,
  221.             dur_timer(&Broadtimer)/1000L);
  222.         return 0;
  223.     }
  224.     stop_timer(&Broadtimer) ;    /* in case it's already running */
  225.     Broadtimer.func = (void (*)())dobroadtick;/* what to call on timeout */
  226.     Broadtimer.arg = NULLCHAR;        /* dummy value */
  227.     set_timer(&Broadtimer,atoi(argv[1])*1000L);    /* set timer duration */
  228.     start_timer(&Broadtimer);        /* and fire it up */
  229.     return 0;
  230. }
  231.  
  232. int Maxax25heard;
  233.  
  234. /* Set the size of the ax.25 heard list */
  235. int doaxhsize(argc, argv, p)
  236. int argc;
  237. char *argv[];
  238. void *p;
  239. {
  240.     return setint(&Maxax25heard,"Max ax-heard",argc,argv);
  241. }
  242.  
  243. void
  244. dobroadtick()
  245. {
  246.     struct iface *ifa;
  247.  
  248.     ifa = Ifaces;
  249.  
  250.     while (ifa != NULL)    {
  251.             if (ifa->flags & AX25_BEACON)
  252.                 ax_bc(ifa);
  253.         ifa = ifa->next;
  254.     }
  255.  
  256.     /* Restart timer */
  257.     start_timer(&Broadtimer) ;
  258. }
  259.  
  260.  
  261.  
  262. /*
  263. ** This is the low-level broadcast function.
  264. */
  265.  
  266. static void ax_bc(axif)
  267. struct iface *axif;
  268. {
  269.     struct mbuf *hbp;
  270.     int i;
  271.     
  272.     /* prepare the header */
  273.     i = strlen(axbctext);
  274.     if((hbp = alloc_mbuf(i)) == NULLBUF)
  275.         return;
  276.         
  277.     hbp->cnt = i;    
  278.     memcpy(hbp->data,axbctext,i);
  279.  
  280.     (*axif->output)(axif, Ax25multi[IDCALL], axif->hwaddr,
  281.         PID_NO_L3, hbp);    /* send it */
  282.  
  283.     /*
  284.     ** Call another function to reset the timer...
  285.     reset_bc_timer();
  286.     */
  287. }
  288.  
  289.  
  290. int
  291. doaxheard(argc,argv,p)
  292. int argc;
  293. char *argv[];
  294. void *p;
  295. {
  296.     struct iface *ifp;
  297.  
  298.     if(argc > 1){
  299.         if((ifp = if_lookup(argv[1])) == NULLIF){
  300.             tprintf(Badinterface,argv[1]);
  301.             return 1;
  302.         }
  303.         if(ifp->output != ax_output){
  304.             tprintf("Interface %s not AX.25\n",argv[1]);
  305.             return 1;
  306.         }
  307.         axheard(ifp);
  308.         return 0;
  309.     }
  310.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  311.         if(ifp->output != ax_output)
  312.             continue;    /* Not an ax.25 interface */
  313.         if(axheard(ifp) == EOF)
  314.             break;
  315.     }
  316.     return 0;
  317. }
  318. int
  319. axheard(ifp)
  320. struct iface *ifp;
  321. {
  322.     int col = 0;
  323.     struct lq *lp;
  324.     char tmp[AXBUF];
  325.  
  326.     if(ifp->hwaddr == NULLCHAR)
  327.         return 0;
  328.  
  329.     tprintf("Interface  Station   Time since send  Pkts sent\n");
  330.     tprintf("%-9s  %-9s   %12s    %7lu\n",ifp->name,pax25(tmp,ifp->hwaddr),
  331.      tformat(secclock() - ifp->lastsent),ifp->rawsndcnt);
  332.  
  333.     tprintf("Station   Time since heard Pkts rcvd : ");
  334.     tprintf("Station   Time since heard Pkts rcvd\n");
  335.     for(lp = Lq;lp != NULLLQ;lp = lp->next){
  336.         if(lp->iface != ifp)
  337.             continue;
  338.         if(col)
  339.             tprintf("  : ");
  340.         if(tprintf("%-9s   %12s    %7lu",pax25(tmp,lp->addr),
  341.          tformat(secclock() - lp->time),lp->currxcnt) == EOF)
  342.             return EOF;
  343.         if(col){
  344.             if(tprintf("\n") == EOF){
  345.                 return EOF;
  346.             } else {
  347.                 col = 0;
  348.             }
  349.         } else {
  350.             col = 1;
  351.         }
  352.     }
  353.     if(col)
  354.         tprintf("\n");
  355.     return 0;
  356. }
  357. int
  358. doaxdest(argc,argv,p)
  359. int argc;
  360. char *argv[];
  361. void *p;
  362. {
  363.     struct iface *ifp;
  364.  
  365.     if(argc > 1){
  366.         if((ifp = if_lookup(argv[1])) == NULLIF){
  367.             tprintf(Badinterface,argv[1]);
  368.             return 1;
  369.         }
  370.         if(ifp->output != ax_output){
  371.             tprintf("Interface %s not AX.25\n",argv[1]);
  372.             return 1;
  373.         }
  374.         axdest(ifp);
  375.         return 0;
  376.     }
  377.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  378.         if(ifp->output != ax_output)
  379.             continue;    /* Not an ax.25 interface */
  380.         if(axdest(ifp) == EOF)
  381.             break;
  382.     }
  383.     return 0;
  384. }
  385. static int
  386. axdest(ifp)
  387. struct iface *ifp;
  388. {
  389.     struct ld *lp;
  390.     struct lq *lq;
  391.     char tmp[AXBUF];
  392.  
  393.     if(ifp->hwaddr == NULLCHAR)
  394.         return 0;
  395.     tprintf("%s:\n",ifp->name);
  396.     tprintf("Station   Last ref         Last heard           Pkts\n");
  397.     for(lp = Ld;lp != NULLLD;lp = lp->next){
  398.         if(lp->iface != ifp)
  399.             continue;
  400.  
  401.         tprintf("%-10s%-17s",
  402.          pax25(tmp,lp->addr),tformat(secclock() - lp->time));
  403.  
  404.         if(addreq(lp->addr,ifp->hwaddr)){
  405.             /* Special case; it's our address */
  406.             tprintf("%-17s",tformat(secclock() - ifp->lastsent));
  407.         } else if((lq = al_lookup(ifp,lp->addr,0)) == NULLLQ){
  408.             tprintf("%-17s","");
  409.         } else {
  410.             tprintf("%-17s",tformat(secclock() - lq->time));
  411.         }
  412.         if(tprintf("%8lu\n",lp->currxcnt) == EOF)
  413.             return EOF;
  414.     }
  415.     return 0;
  416. }
  417.  
  418. static int
  419. doaxfilter(argc,argv,p)
  420. int argc;
  421. char *argv[];
  422. void *p;
  423. {
  424.     if(argc >= 2){
  425.         setint(&axheard_filter_flag,"ax25 heard filter",argc,argv);
  426.     } else {
  427.         tprintf("Usage: ax25 filter <0|1|2|3>\n");
  428.         return 1;
  429.     }
  430.  
  431.     tprintf("Callsign loging by source %sabled, ", (axheard_filter_flag & AXHEARD_NOSRC) ? "dis" : "en");
  432.     tprintf("by destination %sabled\n", (axheard_filter_flag & AXHEARD_NODST) ? "dis" : "en");
  433.     return 0;
  434. }
  435.  
  436. static int
  437. doaxflush(argc,argv,p)
  438. int argc;
  439. char *argv[];
  440. void *p;
  441. {
  442.     struct iface *ifp;
  443.  
  444.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  445.         if(ifp->output != ax_output)
  446.             continue;    /* Not an ax.25 interface */
  447.         axflush(ifp);
  448.     }
  449.     return 0;
  450. }
  451. static void
  452. axflush(ifp)
  453. struct iface *ifp;
  454. {
  455.     struct lq *lp,*lp1;
  456.     struct ld *ld,*ld1;
  457.  
  458.     ifp->rawsndcnt = 0;
  459.     for(lp = Lq;lp != NULLLQ;lp = lp1){
  460.         lp1 = lp->next;
  461.         free((char *)lp);
  462.     }
  463.     Lq = NULLLQ;
  464.     for(ld = Ld;ld != NULLLD;ld = ld1){
  465.         ld1 = ld->next;
  466.         free((char *)ld);
  467.     }
  468.     Ld = NULLLD;
  469. }
  470.  
  471. static
  472. doaxreset(argc,argv,p)
  473. int argc;
  474. char *argv[];
  475. void *p;
  476. {
  477.     struct ax25_cb *axp;
  478.  
  479. #ifndef TNOS_68K
  480.     axp = MK_FP(htoi(argv[1]),8);
  481. #else
  482.     axp = htoi(argv[1]);
  483. #endif
  484.     if(!ax25val(axp)){
  485.         tprintf(Notval);
  486.         return 1;
  487.     }
  488.     reset_ax25(axp);
  489.     return 0;
  490. }
  491.  
  492. /* Display AX.25 link level control blocks */
  493. static
  494. doaxstat(argc,argv,p)
  495. int argc;
  496. char *argv[];
  497. void *p;
  498. {
  499.     register struct ax25_cb *axp;
  500.     char tmp[AXBUF];
  501.     char tmp2[AXBUF];
  502.  
  503.     if(argc < 2){
  504.         tprintf("&AXB Snd-Q   Rcv-Q   Remote    Local     Iface  State\n");
  505.         for(axp = Ax25_cb;axp != NULLAX25; axp = axp->next){
  506.             if(tprintf("%4.4x %-8d%-8d%-10s%-10s%-7s%s\n",
  507.                 FP_SEG(axp),
  508.                 len_q(axp->txq),len_p(axp->rxq),
  509.                 pax25(tmp,axp->remote),
  510.                 pax25(tmp2,axp->local),
  511.                 axp->iface?axp->iface->name:"",
  512.                 Ax25states[axp->state]) == EOF)
  513.                     return 0;
  514.         }
  515.         return 0;
  516.     }
  517. #ifndef TNOS_68K
  518.     axp = MK_FP(htoi(argv[1]),8);
  519. #else
  520.     axp = htoi(argv[1]);
  521. #endif
  522.     if(!ax25val(axp)){
  523.         tprintf(Notval);
  524.         return 1;
  525.     }
  526.     st_ax25(axp);
  527.     return 0;
  528. }
  529. /* Dump one control block */
  530. void
  531. st_ax25(axp)
  532. register struct ax25_cb *axp;
  533. {
  534.     char tmp[AXBUF];
  535.     char tmp2[AXBUF];
  536.  
  537.     if(axp == NULLAX25)
  538.         return;
  539.     tprintf("&AXB Local     Remote    Iface  RB V(S) V(R) Unack P Retry State\n");
  540.  
  541.     tprintf("%4.4x %-9s %-9s %-6s %c%c",FP_SEG(axp),
  542.         pax25(tmp,axp->local),
  543.         pax25(tmp2,axp->remote),
  544.         axp->iface?axp->iface->name:"",
  545.         axp->flags.rejsent ? 'R' : ' ',
  546.         axp->flags.remotebusy ? 'B' : ' ');
  547.     tprintf(" %4d %4d",axp->vs,axp->vr);
  548.     tprintf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  549.     tprintf(" %02u/%02u",axp->retries,axp->n2);
  550.     tprintf(" %s\n",Ax25states[axp->state]);
  551.     tprintf("srtt = %lu mdev = %lu ",axp->srt,axp->mdev);
  552.     tprintf("T1: ");
  553.     if(run_timer(&axp->t1))
  554.         tprintf("%lu",read_timer(&axp->t1));
  555.     else
  556.         tprintf("stop");
  557.     tprintf("/%lu ms; ",dur_timer(&axp->t1));
  558.  
  559.     tprintf("T3: ");
  560.     if(run_timer(&axp->t3))
  561.         tprintf("%lu",read_timer(&axp->t3));
  562.     else
  563.         tprintf("stop");
  564.     tprintf("/%lu ms; ",dur_timer(&axp->t3));
  565.  
  566.     tprintf("T4: ");
  567.     if(run_timer(&axp->t4))
  568.         tprintf("%lu",(read_timer(&axp->t4)/1000L));
  569.     else
  570.         tprintf("stop");
  571.     tprintf("/%lu sec\n",(dur_timer(&axp->t4)/1000L));
  572. }
  573.  
  574. /* Set limit on retransmission backoff */
  575. static
  576. doblimit(argc,argv,p)
  577. int argc;
  578. char *argv[];
  579. void *p;
  580. {
  581.     return setlong(&Blimit,"blimit",argc,argv);
  582. }
  583.  
  584. /* Display or change our AX.25 address */
  585. static
  586. domycall(argc,argv,p)
  587. int argc;
  588. char *argv[];
  589. void *p;
  590. {
  591. #ifdef MAILBOX
  592.     extern void setmbnrid();
  593. #endif
  594.     char tmp[AXBUF];
  595.  
  596.     if(argc < 2){
  597.         tprintf("%s\n",pax25(tmp,Mycall));
  598.         return 0;
  599.     }
  600.     if(setcall(Mycall,argv[1]) == -1)
  601.         return -1;
  602. #ifdef MAILBOX
  603.     setmbnrid();
  604. #endif
  605.     return 0;
  606. }
  607.  
  608. /* Control AX.25 digipeating */
  609. static
  610. dodigipeat(argc,argv,p)
  611. int argc;
  612. char *argv[];
  613. void *p;
  614. {
  615.     return(dosetflag(argc,argv,p,AX25_DIGI, 1));
  616. }
  617.  
  618. /* Configure a port to do ax.25 heard logging */
  619. static int
  620. doaxhport(argc,argv,p)
  621. int argc;
  622. char *argv[];
  623. void *p;
  624. {
  625.     return(dosetflag(argc,argv,p,LOG_AXHEARD, 1));
  626. }
  627.  
  628. /* Configure a port to do ax.25 beacon broadcasting */
  629. static int
  630. dobcport(argc,argv,p)
  631. int argc;
  632. char *argv[];
  633. void *p;
  634. {
  635.     return(dosetflag(argc,argv,p,AX25_BEACON, 1));
  636. }
  637.  
  638. static
  639. doversion(argc,argv,p)
  640. int argc;
  641. char *argv[];
  642. void *p;
  643. {
  644.     return setshort(&Axversion,"AX25 version",argc,argv);
  645. }
  646.  
  647. static
  648. doaxirtt(argc,argv,p)
  649. int argc;
  650. char *argv[];
  651. void *p;
  652. {
  653.     return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
  654. }
  655.  
  656. /* Set idle timer */
  657. static
  658. dot3(argc,argv,p)
  659. int argc;
  660. char *argv[];
  661. void *p;
  662. {
  663.     return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
  664. }
  665.  
  666. /* Set link redundancy timer */
  667. static
  668. dot4(argc,argv,p)
  669. int argc;
  670. char *argv[];
  671. void *p;
  672. {
  673.     return setlong(&T4init,"Link redundancy timer (sec)",argc,argv);
  674. }
  675.  
  676. /* Set retry limit count */
  677. static
  678. don2(argc,argv,p)
  679. int argc;
  680. char *argv[];
  681. void *p;
  682. {
  683.     return setshort(&N2,"Retry limit",argc,argv);
  684. }
  685. /* Force a retransmission */
  686. static
  687. doaxkick(argc,argv,p)
  688. int argc;
  689. char *argv[];
  690. void *p;
  691. {
  692.     struct ax25_cb *axp;
  693.  
  694. #ifndef TNOS_68K
  695.     axp = MK_FP(htoi(argv[1]),8);
  696. #else
  697.     axp = htoi(argv[1]);
  698. #endif
  699.     if(!ax25val(axp))    {
  700.         tprintf(Notval);
  701.         return 1;
  702.     }
  703.     kick_ax25(axp);
  704.     return 0;
  705. }
  706.  
  707. /* Set maximum number of frames that will be allowed in flight */
  708. static
  709. domaxframe(argc,argv,p)
  710. int argc;
  711. char *argv[];
  712. void *p;
  713. {
  714.     return setshort(&Maxframe,"Window size (frames)",argc,argv);
  715. }
  716.  
  717. /* Set maximum length of I-frame data field */
  718. static
  719. dopaclen(argc,argv,p)
  720. int argc;
  721. char *argv[];
  722. void *p;
  723. {
  724.     return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
  725. }
  726. /* Set size of I-frame above which polls will be sent after a timeout */
  727. static
  728. dopthresh(argc,argv,p)
  729. int argc;
  730. char *argv[];
  731. void *p;
  732. {
  733.     return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
  734. }
  735.  
  736. /* Set high water mark on receive queue that triggers RNR */
  737. static
  738. doaxwindow(argc,argv,p)
  739. int argc;
  740. char *argv[];
  741. void *p;
  742. {
  743.     return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
  744. }
  745. /* End of ax25 subcommands */
  746.  
  747. /* Initiate interactive AX.25 connect to remote station */
  748. int
  749. doconnect(argc,argv,p)
  750. int argc;
  751. char *argv[];
  752. void *p;
  753. {
  754.     struct sockaddr_ax fsocket;
  755.     struct session *sp;
  756.     struct iface *ifp;
  757.     int ndigis,i;
  758.     char digis[MAXDIGIS][AXALEN];
  759.     char target[AXALEN];
  760.     int split = 0;
  761.  
  762.     /*Make sure this comes from console - WG7J*/
  763.     if(Curproc->input != Command->input)
  764.         return 0;
  765.  
  766. #ifdef ALLSERV
  767.     if(argv[0][0] == 's')   /* use split screen */
  768.         split  = 1;
  769. #endif
  770.  
  771.     if(((ifp = if_lookup(argv[1])) != NULLIF) && (ifp->type != CL_AX25)) {
  772.         tprintf("Iface %s not an AX25 type interface\n",argv[1]);
  773.         return 1;
  774.     }
  775.  
  776.     if(setcall(target,argv[2]) == -1){
  777.         tprintf("Bad callsign %s\n", argv[2]);
  778.         return 1;
  779.     }
  780.  
  781.     /* If digipeaters are given, put them in the routing table */
  782.     if(argc > 3){
  783.         if(setcall(target,argv[2]) == -1){
  784.             tprintf("Bad callsign %s\n", argv[2]);
  785.             return 1;
  786.         }
  787.         ndigis = argc - 3;
  788.         if(ndigis > MAXDIGIS){
  789.             tprintf("Too many digipeaters\n");
  790.             return 1;
  791.         }
  792.         for(i=0;i<ndigis;i++){
  793.             if(setcall(digis[i],argv[i+3]) == -1){
  794.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  795.                 return 1;
  796.             }
  797.         }
  798.         if(ax_add(target,AX_AUTO,digis,ndigis,ifp) == NULLAXR){
  799.             tprintf("Route add failed\n");
  800.             return 1;
  801.         }
  802.     }
  803.     /* Allocate a session descriptor */
  804.     if((sp = newsession(argv[2],AX25TNC,split)) == NULLSESSION){
  805.         tputs(TooManySessions);
  806.         return 1;
  807.     }
  808.     if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  809.         tputs(Nosock);
  810.         freesession(sp);
  811.         keywait(NULLCHAR,1);
  812.         return 1;
  813.     }
  814.     fsocket.sax_family = AF_AX25;
  815.     setcall(fsocket.ax25_addr,argv[2]);
  816.     strncpy(fsocket.iface,argv[1],ILEN);
  817.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
  818. }
  819.  
  820. /* Display and modify AX.25 routing table */
  821. static int
  822. doaxroute(argc,argv,p)
  823. int argc;
  824. char *argv[];
  825. void *p;
  826. {
  827.     char tmp[AXBUF];
  828.     int i,ndigis;
  829.     register struct ax_route *axr;
  830.     char target[AXALEN],digis[MAXDIGIS][AXALEN];
  831.     struct iface *iface;
  832.  
  833.     if(argc < 2){
  834.         tputs("Target    Iface  Type  Mode Digipeaters\n");
  835.         for(axr = Ax_routes;axr != NULLAXR;axr = axr->next){
  836.             tprintf("%-10s%-7s%-6s",pax25(tmp,axr->target),
  837.                 axr->iface->name,axr->type == AX_LOCAL ? "Local":"Auto");
  838.             switch(axr->mode){
  839.             case AX_VC_MODE:
  840.                 tputs(" VC ");
  841.                 break;
  842.             case AX_DATMODE:
  843.                 tputs(" DG ");
  844.                 break;
  845.             case AX_DEFMODE:
  846.                 tputs(" IF ");
  847.                 break;
  848.             default:
  849.                 tputs(" ?? ");
  850.                 break;
  851.             }
  852.  
  853.             for(i=0;i<axr->ndigis;i++){
  854.                 tprintf(" %s",pax25(tmp,axr->digis[i]));
  855.             }
  856.             if(tprintf("\n") == EOF)
  857.                 return 0;
  858.         }
  859.         return 0;
  860.     }
  861.     if(argc < 4){
  862.         tprintf("Usage: ax25 route add <target> <iface> [digis...]\n");
  863.         tprintf("       ax25 route drop <target> <iface>\n");
  864.         tprintf("       ax25 route mode <target> <iface> [mode]\n");
  865.         return 1;
  866.     }
  867.     if(setcall(target,argv[2]) == -1){
  868.         tprintf("Bad target %s\n",argv[2]);
  869.         return 1;
  870.     }
  871.     if((iface = if_lookup(argv[3])) == NULLIF){
  872.         tprintf(Badinterface,argv[3]);
  873.         return 1;
  874.     }
  875.     switch(argv[1][0]){
  876.     case 'a':    /* Add route */
  877.         ndigis = argc - 4;
  878.         if(ndigis > MAXDIGIS){
  879.             tprintf("Too many digipeaters\n");
  880.             return 1;
  881.         }
  882.         for(i=0;i<ndigis;i++){
  883.             if(setcall(digis[i],argv[i+4]) == -1){
  884.                 tprintf("Bad digipeater %s\n",argv[i+4]);
  885.                 return 1;
  886.             }
  887.         }
  888.         if(ax_add(target,AX_LOCAL,digis,ndigis,iface) == NULLAXR){
  889.             tprintf("Failed\n");
  890.             return 1;
  891.         }
  892.         break;
  893.     case 'd':    /* Drop route */
  894.         if(ax_drop(target,iface) == -1){
  895.             tprintf("Not in table\n");
  896.             return 1;
  897.         }
  898.         break;
  899.     case 'm':    /* Alter route mode */
  900.         if((axr = ax_lookup(target,iface)) == NULLAXR){
  901.             tprintf("Not in table\n");
  902.             return 1;
  903.         }
  904.         switch(argv[4][0]){
  905.         case 'i':    /* use default interface mode */
  906.             axr->mode = AX_DEFMODE;
  907.             break;
  908.         case 'v':    /* use virtual circuit mode */
  909.             axr->mode = AX_VC_MODE;
  910.             break;
  911.         case 'd':    /* use datagram mode */
  912.             axr->mode = AX_DATMODE;
  913.             break;
  914.         default:
  915.             tprintf("Unknown mode %s\n", argv[4]);
  916.             return 1;
  917.         }
  918.         break;
  919.     default:
  920.         tprintf("Unknown command %s\n",argv[1]);
  921.         return 1;
  922.     }
  923.     return 0;
  924. }
  925.  
  926. /* ax25 timers type - linear v exponential */
  927. static
  928. doaxtype(argc,argv,p)
  929. int argc ;
  930. char *argv[] ;
  931. void *p ;
  932. {
  933.     extern int lapbtimertype;
  934.  
  935.     if (argc < 2) {
  936.         tprintf("AX25 timer type is ");
  937.         switch(lapbtimertype){
  938.         case 2:
  939.             tprintf("original\n");
  940.             break;
  941.         case 1:
  942.             tprintf("linear\n");
  943.             break;
  944.         case 0:
  945.             tprintf("exponential\n");
  946.             break;
  947.         }
  948.         return 0 ;
  949.     }
  950.     
  951.     switch (argv[1][0]) {
  952.         case 'o':
  953.         case 'O':
  954.             lapbtimertype = 2 ;
  955.             break ;
  956.         case 'l':
  957.         case 'L':
  958.             lapbtimertype = 1 ;
  959.             break ;
  960.         case 'e':
  961.         case 'E':
  962.             lapbtimertype = 0 ;
  963.             break ;
  964.         default:
  965.             tprintf("use: ax25 timertype [original|linear|exponential]\n") ;
  966.             return -1 ;
  967.     }
  968.  
  969.     return 0 ;
  970. }
  971.  
  972. #ifdef TUTOR
  973. /* Display or change an AX.25 tutorial-type call */
  974. static
  975. docall(argc,argv,p, call)
  976. int argc;
  977. char *argv[];
  978. void *p;
  979. char call[];
  980. {
  981. char tmp[AXBUF];
  982.  
  983.     if(argc < 2)    {
  984.         tprintf("%s\n",pax25(tmp,call));
  985.         return 0;
  986.     }
  987.     if(setcall(call,argv[1]) == -1)
  988.         return -1;
  989.     return 0;
  990. }
  991.  
  992.  
  993. /* Display or change our AX.25 tutorial call */
  994. static
  995. dotutorcall(argc,argv,p)
  996. int argc;
  997. char *argv[];
  998. void *p;
  999. {
  1000.     return (docall (argc, argv, p, Tcall));
  1001. }
  1002.  
  1003.  
  1004. /* Display or change our AX.25 info call */
  1005. static
  1006. doinfocall(argc,argv,p)
  1007. int argc;
  1008. char *argv[];
  1009. void *p;
  1010. {
  1011.     return (docall (argc, argv, p, Icall));
  1012. }
  1013.  
  1014.  
  1015. /* Display or change our AX.25 news call */
  1016. static
  1017. donewscall(argc,argv,p)
  1018. int argc;
  1019. char *argv[];
  1020. void *p;
  1021. {
  1022.     return (docall (argc, argv, p, Ncall));
  1023. }
  1024. #endif
  1025.  
  1026.